/**
 * \file ssi_link_layer.h
 *
 * \brief declaration file of SSI library to handle the ssi link layer frames
 *
 * \author Santiago Carmona Meco
 *
 * Contact santiago.carmonads@gmail.com
 *
 */

// ****************************************
// 	CHANGE LOG
//                SEP-2011  scarmona  Creating this file
//                2011-2012 scarmona  Development of the library and source code modifications
//                FEB-2013  scarmona  Modifications of type names, variable names and update
// 									  of comments with format of doxygen
//				  26-4-2013 scarmona  Subtle modifications of code style and type definitions in burst structs
//				  21-6-2013 scarmona  Changes in parameters of builder functions and several names
//
// ****************************************

#ifndef __SSI_LINK_LAYER_H_
#define __SSI_LINK_LAYER_H_


#include <public/basic_types.h>
#include <public/crc_16.h>


#define DATA_FRAME_LENGTH 50
#define SIGNAL_FRAME_LENGTH 17

//mask to frame's flags
#define MASK_ACK_SSI 0x01
#define MASK_DISCOVERY_SSI 0x02
#define MASK_SPACE_SSI 0x04
#define MASK_GROUND_SSI 0x08
#define MASK_DATA_SSI 0x10



#define MASK_BIDIRECTIONAL_SSI 0x8000


typedef enum FrameTypeReceived {FrameTypeIsSSIDefault,FrameTypeIsSSIAck,FrameTypeIsSSIDiscovery,FrameTypeIsSSIData,FrameTypeIsSSIUnidirectional} FrameTypeReceived_t;


typedef struct ssi_link_layer_data_frame_info_t {
    byte_t radio_id[6];
    word16_t sensor_id;
    byte_t  flags;
    byte_t reserved[6];
	byte_t  length;
	byte_t  data[32];
}
SSI_data_frame_t;

typedef struct ssi_link_layer_signal_frame_info_t {
    byte_t radio_id[6];
    word16_t sensor_id;
    byte_t  flags;
    byte_t reserved[6];
}
SSI_signal_frame_t;

/**
 * \brief get radio id from ssi link frame
 *
 * \param pFrame bytes of the complete frame
 * \param pRadioId bytes where radio_id is copied
 */
void ssi_link_layer_get_radio_id(byte_t * pFrame, byte_t *pRadioId);

/**
 * \brief get radio id from ssi link frame
 *
 * \param pFrame bytes of the complete frame
 *
 * \return word16 corresponding to the sensor_id of the frame
 */
word16_t ssi_link_layer_get_sensor_id(byte_t *pFrame);

/**
 * \brief get flags from ssi link frame
 *
 * \param pFrame bytes of the complete frame
 *
 * \return byte corresponding to the flags of the frame
 */
byte_t ssi_link_layer_get_flags(byte_t * pFrame);

/**
 * \brief get reserved field from ssi link frame
 *
 * \param pFrame bytes of the complete frame
 * \param pReserved bytes where the reserved field is copied
 */
void ssi_link_layer_get_reserved(byte_t * pFrame, byte_t *pReserved);

/**
 * \brief get data length from ssi link frame
 *
 * \param pFrame bytes of the complete frame
 * \return byte corresponding to the data length of the frame
 */
byte_t ssi_link_layer_get_data_length(byte_t * pFrame);

/**
 * \brief copy data from ssi link frame and return the data length copied
 *
 * \param pFrame bytes of the complete frame
 * \param pData bytes where the data field is copied
 */
void ssi_link_layer_get_data(byte_t *pFrame, byte_t *pData);

/**
 * \brief check if ack flag is true
 *
 * \param pFrame bytes of the complete frame
 *
 * \return true if ack field is 1
 */
bool_t ssi_link_layer_is_ack(byte_t * pFrame);
/**
 * \brief check if discovery flag is true
 *
 * \param pFrame bytes of the complete frame
 *
 * \return true if discovery field is 1
 */
bool_t ssi_link_layer_is_discovery(byte_t * pFrame);

/**
 * \brief check if space flag is true
 *
 * \param pFrame bytes of the complete frame
 *
 * \return true if space field is 1
 */
bool_t ssi_link_layer_is_space(byte_t * pFrame);
/**
 * \brief check if ground flag is true
 *
 * \param pFrame bytes of the complete frame
 *
 * \return true if ground field is 1
 */
bool_t ssi_link_layer_is_ground(byte_t * pFrame);
/**
 * \brief check if data flag is true
 *
 * \param pFrame bytes of the complete frame
 *
 * \return true if data field is 1, false if not
 */
bool_t ssi_link_layer_is_data(byte_t * pFrame);


/**
 * \brief this function  checks if frame is from bidirectional
 *  sensor or unidirectional sensor
 *
 *  \param sensorId sensor id from bidirectional sensor
 *
 *  \return if sensorId is from bidirectional sensor returns true
 */
bool_t ssi_link_layer_sensor_id_is_bidirectional(word16_t sensorId);

/**
 * \brief this function returns if the frame is an ack, a data frame or
 *  from the unidirectional sensor
 *
 * \param pFrame bytes of the complete frame
 *
 * \return enum with the frame type
 */
FrameTypeReceived_t ssi_link_layer_get_frame_type(byte_t * pFrame);

/**
 * \brief checks crc
 *
 * \param pFrame bytes of the complete frame
 *
 * \return true if crc is ok
 */
bool_t ssi_link_layer_check_data_frame_crc(byte_t * pFrame);

/**
 * \brief checks crc
 *
 * \param pFrame bytes of the complete frame
 *
 * \return true if crc is ok
 */
bool_t ssi_link_layer_check_signal_frame_crc(byte_t * pFrame);


/**
 * \brief function that adds the CRC field to the final frame
 *  used within the function that builds the plot
 *
 * \param pFrame bytes of the complete frame
 */
void ssi_link_layer_add_crc_to_data_frame(byte_t * pframe);

/**
 * \brief function that adds the CRC field to the final frame
 *  used within the function that builds the plot
 *
 * \param pFrame bytes of the complete frame
 */
void ssi_link_layer_add_crc_to_signal_frame(byte_t * pframe);

/**
 * \brief function to build the final data frame
 *
 * \param pFrame bytes of the complete data frame
 * \param pFrameInfo struct with the values for the frame
 */
void ssi_link_layer_build_data_frame(byte_t * pFrame, SSI_data_frame_t frameInfo);

/**
 * \brief function to build the final signal frame
 *
 * \param pFrame bytes of the complete signal frame
 * \param pFrameInfo struct with the values for the frame
 */
void ssi_link_layer_build_signal_frame(byte_t * pFrame, SSI_signal_frame_t frameInfo);


/**
 * \brief this function builds the explicit Ack frame
 *
 * \param pFrame bytes of the complete frame
 */
void ssi_link_layer_build_ack(byte_t *pFrame,byte_t *radioId,word16_t sensorId);


/*
 * \brief this function gets the frame info for each type of data frame
 *
 * \param pFrame bytes of the complete data frame
 * \param pFrameInfo struct where the frame values are copied
 */
void ssi_link_layer_get_data_frame_info(byte_t * pFrame, SSI_data_frame_t *pFrameInfo);
/*
 * \brief this function gets the frame info for each type of signal frame
 *
 * \param pFrame bytes of the complete signal frame
 * \param pFrameInfo struct where the frame values are copied
 */
void ssi_link_layer_get_signal_frame_info(byte_t * pFrame, SSI_signal_frame_t *pFrameInfo);



#endif /* __SSI_LINK_LAYER_H_ */
